package com.mti;

import java.util.ArrayList;
import java.util.Date;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class ParserXMLHandler extends DefaultHandler {
	// nom des tags XML
	private final String FORECAST_INFORMATION = "forecast_information";
	private final String POSTAL_CODE = "postal_code";
	private final String FORECAST_DATE = "forecast_date";
	private final String CURRENT_CONDITIONS = "current_conditions";
	private final String TEMP_F = "temp_f";
	private final String TEMP_C = "temp_c";
	private final String HUMIDITY = "humidity";
	private final String WIND_CONDITION = "wind_condition";
	private final String FORECAST_CONDITIONS = "forecast_conditions";
	private final String DAY = "day_of_week";
	private final String LOW = "low";
	private final String HIGH = "high";
	private final String ICON = "icon";
	private final String CONDITION = "condition";
	private final String WEATHER = "weather";
	
	// XML attribute to parse
	private String dataAttribute = "data";
	
	// Array list de feeds
	private ArrayList<CityWeather> entries;
	
	// Boolean permettant de savoir si nous sommes � l'int�rieur d'un cityWeather
	private boolean inCityWeather;
	// Boolean permettant de savoir si nous sommes � l'int�rieur d'un Condition
	private boolean inCurrentCondition;
	// Boolean permettant de savoir si nous sommes � l'int�rieur d'un Condition
	private boolean inForecastCondition;
	
	// Feed courant
	private CityWeather cityWeather;
	private Condition condition;
	
	// Buffer permettant de contenir les donn�es d'un tag XML
	private StringBuffer buffer;
	
	@Override
	public void processingInstruction(String target, String data) throws SAXException {
		super.processingInstruction(target, data);
	}
	
	public ParserXMLHandler() {
		super();
	}
	
	// * Cette m�thode est appel�e par le parser une et une seule
	// * fois au d�marrage de l'analyse de votre flux xml.
	// * Elle est appel�e avant toutes les autres m�thodes de l'interface,
	// * � l'exception unique, �videmment, de la m�thode setDocumentLocator.
	// * Cet �v�nement devrait vous permettre d'initialiser tout ce qui doit
	// * l'�tre avant led�but du parcours du document.
	@Override
	public void startDocument() throws SAXException {
		super.startDocument();
		entries = new ArrayList<CityWeather>();
	}
	
	/*
	 * Fonction �tant d�clench�e lorsque le parser trouve un tag XML
	 * C'est cette m�thode que nous allons utiliser pour instancier un nouveau feed
 	*/
	@Override
	public void startElement(String uri, String localName, String name,	Attributes attributes) throws SAXException {		
		// Nous r�initialisons le buffer a chaque fois qu'il rencontre un item
		buffer = new StringBuffer();
		
		// Ci dessous, localName contient le nom du tag rencontr�
		// Nous avons rencontr� un tag FORECAST_INFORMATION, il faut donc instancier un nouvel objet CityWeather
		if (localName.equalsIgnoreCase(FORECAST_INFORMATION)){
			this.cityWeather = new CityWeather();
			inCityWeather = true;
		}
		
		if (localName.equalsIgnoreCase(CURRENT_CONDITIONS)){
			inCurrentCondition = true;
		}
		
		// Nous avons rencontr� un tag FORECAST_CONDITIONS, il faut donc instancier un nouvel objet Condition
		if (localName.equalsIgnoreCase(FORECAST_CONDITIONS)){
			this.condition = new Condition();
			inForecastCondition = true;
		}
		
		// Fill CityWeather basic info
		if (localName.equalsIgnoreCase(POSTAL_CODE)){
			if(inCityWeather){
				this.cityWeather.setCity(attributes.getValue(dataAttribute));
				buffer = null;
			}
		}
		
		if (localName.equalsIgnoreCase(FORECAST_DATE)){
			if(inCityWeather){
				String[] temp = attributes.getValue(dataAttribute).split("-");
				this.cityWeather.setDate(new Date(
						Integer.parseInt(temp[0]),
						Integer.parseInt(temp[1]),
						Integer.parseInt(temp[2])));
				buffer = null;
			}
		}
		
		// Fill CityWeather current condition
		if (localName.equalsIgnoreCase(TEMP_F)){
			if(inCurrentCondition && attributes.getValue(dataAttribute) != ""){
				this.cityWeather.setTempF(Integer.parseInt(attributes.getValue(dataAttribute)));
				buffer = null;
			}
		}
		
		if (localName.equalsIgnoreCase(TEMP_C)){
			if(inCurrentCondition && attributes.getValue(dataAttribute) != ""){
				this.cityWeather.setTempC(Integer.parseInt(attributes.getValue(dataAttribute)));
				buffer = null;
			}
		}
		
		if (localName.equalsIgnoreCase(HUMIDITY)){
			if(inCurrentCondition){
				this.cityWeather.setHumidity(attributes.getValue(dataAttribute).replace("Humidity: ", ""));
				buffer = null;
			}
		}
		
		if (localName.equalsIgnoreCase(WIND_CONDITION)){
			if(inCurrentCondition){
				this.cityWeather.setWindCondition(attributes.getValue(dataAttribute));
				buffer = null;
			}
		}
		
		// Fill forecast condition
		if (localName.equalsIgnoreCase(DAY)){
			if(inForecastCondition){
				this.condition.setDay(attributes.getValue(dataAttribute));
				buffer = null;
			}
		}
		
		if (localName.equalsIgnoreCase(LOW)){
			if(inForecastCondition && attributes.getValue(dataAttribute) != ""){
				this.condition.setLow(Integer.parseInt(attributes.getValue(dataAttribute)));
				buffer = null;
			}
		}
		
		if (localName.equalsIgnoreCase(HIGH)){
			if(inForecastCondition && attributes.getValue(dataAttribute) != ""){
				this.condition.setHigh(Integer.parseInt(attributes.getValue(dataAttribute)));
				buffer = null;
			}
		}
		
		// In both current and forecast
		if (localName.equalsIgnoreCase(CONDITION)){
			if(inCurrentCondition){
				this.cityWeather.setCondition(attributes.getValue(dataAttribute));
			} else if (inForecastCondition) {
				this.condition.setCondition(attributes.getValue(dataAttribute));
			}

			buffer = null;
		}
		
		if (localName.equalsIgnoreCase(ICON)){
			if(inCurrentCondition){
				this.cityWeather.setIconPath(attributes.getValue(dataAttribute));
			} else if (inForecastCondition) {
				this.condition.setIconPath(attributes.getValue(dataAttribute));
			}
			
			buffer = null;
		}
	}
	
	// * Fonction �tant d�clench�e lorsque le parser � pars�
	// * l'int�rieur de la balise XML La m�thode characters
	// * a donc fait son ouvrage et tous les caract�re inclus
	// * dans la balise en cours sont copi�s dans le buffer
	// * On peut donc tranquillement les r�cup�rer pour compl�ter
	// * notre objet currentFeed
	@Override
	public void endElement(String uri, String localName, String name) throws SAXException {		
		// Add Condition to CityWeather list
		if(localName.equalsIgnoreCase(CURRENT_CONDITIONS)){
			if(inCurrentCondition){
				inCurrentCondition = false;
			}
		}
		
		if(localName.equalsIgnoreCase(FORECAST_CONDITIONS)){
			if(inForecastCondition){
				this.cityWeather.getListCondition().add(condition);
				inForecastCondition = false;
			}
		}
		
		if (localName.equalsIgnoreCase(WEATHER)){
			entries.add(cityWeather);
			inCityWeather = false;
		}
	}
	
	// * Tout ce qui est dans l'arborescence mais n'est pas partie
	// * int�grante d'un tag, d�clenche la lev�e de cet �v�nement.
	// * En g�n�ral, cet �v�nement est donc lev� tout simplement
	// * par la pr�sence de texte entre la balise d'ouverture et
	// * la balise de fermeture
	public void characters(char[] ch,int start, int length)	throws SAXException{
		String lecture = new String(ch,start,length);
		if(buffer != null) buffer.append(lecture);
	}
	
	// cette m�thode nous permettra de r�cup�rer les donn�es
	public ArrayList<CityWeather> getData(){
		return entries;
	}
}